package utils;

import static java.util.stream.Collectors.toList;

import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.phantomthief.util.CursorIterator;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 原理: 一个迭代器, 每次查分页大小.
 * 通过多查一位来检查否有剩余元素.返回元素时subList还是返回分页大小的元素. 假如查到的数据少于多出的一位就表示遍历结束.
 * 疑问: 什么场景需要倒着查呢?
 *
 * @author jiangfeng on 2022/7/3
 */
public class CursorIterableTest {

    private static final int BUFFER_SIZE = 10;

    Logger log  = LoggerFactory.getLogger(CursorIterableTest.class);

    @Test
    public void test() {
        CursorIterator<Integer, TestModle> testModles = CursorIterator.<Integer, TestModle> newGenericBuilder()
                .bufferSize(BUFFER_SIZE)
                .cursorExtractor(TestModle::getId)
                .start(Integer.MAX_VALUE)
                .buildEx(((cursor, limit) -> queryByCursor(cursor, limit)));

        log.info("start");
        System.out.println("start");
        // testModles.forEach(e-> System.out.println(e));

        testModles.stream().forEach(e -> System.out.println("stream test:" + e));
    }

    Integer count = 100;
    Integer max = 100;

    private List<TestModle> queryByCursor(Integer cursor, int limit) {
        log.info("queryByCursor:cursor:{},limit:{}", cursor, limit);
        System.out.println("queryByCursor cursor:" + cursor + " limit: " + limit);
        if (cursor == null) {
            return Collections.emptyList();
        }
        if (cursor <= 0) {
            return Collections.emptyList();
        }

        return Stream.generate(() -> new TestModle(count--, String.valueOf(count)))
                .limit(limit)
                .collect(toList());

    }


    class TestModle {
        private int id;
        private String name;

        public TestModle(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}
